<template>
	<div class="node-db-console">
		<Row type="flex">
			<Col :span="5"
			     class="left-box">
			<Selector label="数据源"
			          @selectChange="sourceChange"
			          :initData="statusData && statusData.source"
			          :data="statusData && statusData.source"
			          :initValue="statusData && statusData.source && statusData.source.id"
			          :path="path.source"></Selector>
			<hr>
			<SelectPanel @select="entityChange"
			             :data="entityList"
			             :loading="entityLoading"
			             :open="true">
				<template slot="option"
				          slot-scope="data">
					<div class="entity-option">
						<span class="name">
							{{data.item.TABLE_NAME}}
						</span>
						<span class="type-code">
							<Button type="text"
							        size="small"
							        title="查看"
							        @click="viewEntity(data.item.TABLE_NAME)"
							        icon="navicon"></Button>
							<Button type="text"
							        size="small"
							        title="复制"
							        @click="copyName(data.item.TABLE_NAME)"
							        icon="ios-copy"></Button>
						</span>
					</div>
				</template>
			</SelectPanel>
			</Col>
			<Col :span="19"
			     class="right-box">
			<div class="tool-box">
				<Button @click="execute"
				        :loading="executing"
				        type="primary"
				        icon="flash">执行</span>
				</Button>
				<Button icon="ios-download"
				        type="info"
				        @click="exportConfirm"
				        :disabled="!resultModel"
				        :loading="exportLoading">导出数据</Button>
				<Button @click="clearSql"
				        type="ghost">清空</Button>
				<Button @click="presetConfigShow"
				        :loading="presetModelLoading"
				        icon="navicon-round"
				        type="success"
				        class="pull-right">预置脚本</Button>
			</div>
			<hr>
			<Input v-show="false"
			       v-model="sqlName"
			       class="name-input">
			<span slot="prepend">描述</span>
			</Input>
			<CodeEditor ref="editor"
			            lang="sql"
			            v-model="sqlString"></CodeEditor>
			<hr>
			<div class="data-box">
				<GridPanel :extPostData="executeData"
				           :initFetch="false"
				           :hasSearch="false"
				           v-if="resultModel"
				           :enableChangeData="true"
				           ref="dataTable"
				           :loading="executing"
				           :data="resultData"
				           :model="resultModel"></GridPanel>
			</div>
			</Col>
		</Row>
		<Modals class="modal-full modal-node"
		        width="90%"
		        v-model="presetModal"
		        title="预置脚本">
			<div>
				<GridPanel v-if="presetModel"
				           @action-event-trigger="presetActionEvent"
				           :model="presetModel"></GridPanel>
			</div>
		</Modals>
		<Modals v-model="entityModal"
		        class="modal-full modal-node"
		        width="1200"
		        title="实体预览">
			<Tabs @on-click="tabClick"
			      v-model="tabOn">
				<Tab-pane name="entity"
				          label="实体结构">
					<Data-table :ref="'table-1'"
					            :model="structModel"
					            :data="structData"
					            :hasCheck="false"></Data-table>
				</Tab-pane>
				<Tab-pane name="sample"
				          label="数据样本">
					<grid-panel v-if="sampleLoad"
					            ref="sampleTable"
					            :hasSearch="false"
					            :hasAction="false"
					            :model="sampleModel"
					            :hasCheck="false"
					            @updateStatus="tableUpdateStatus"></grid-panel>
				</Tab-pane>
			</Tabs>
			<div slot="footer">
				<Button type="primary"
				        @click="entityModal=false">关闭</Button>
			</div>
		</Modals>
	</div>
</template>
<script>
import $ from '@/common';
import DataTable from '@/components/gridTableSample';
import GridPanel from '@/node/gridPanel/index';

import Selector from '@/components/x_selector';
import SelectPanel from '@/components/selectPanel';
import CodeEditor from '@/element/codeEditor';
import Modals from '@/element/modal';
import HeightLight from '@/directives/height-light';
import ClickOut from '@/directives/click-out';
import { billParser } from '@/common/parser';

var Base64 = require('js-base64').Base64;
export default {
	props: {
		statusData: {},
	},
	data() {
		return {
			path: {
				_source: '/service/{app}/pf/rdbs',
				source: '/service/{app}/dataset/data/db_rdb',
				entity: '/service/{app}/pf/rdb/entities/{code}',
				execute: '/service/{app}/dbconsole/execute',
				export: '/service/{app}/dbconsole/exp',
				model: '/service/{app}/bill/model/dbconsole_log',
				//实体子弹查询
				entity_field: '/service/cs/pf/rdb/entity/struct/cc/{entity_code}',
				//preset相关暂时弃用，直接采用gp的方法处理预置数据
				preset: {
					list: '/service/cs/list',
					delete: '/service/cs/list',
				},
				struct: '/service/{app}/pf/rdb/entity/struct/{ds_code}/{entity_code}',
				sample: 'service/{app}/pf/rdb/data/{ds_code}/{entity_code}',
			},
			presetVisible: false,
			resultData: [],
			presetList: [],
			presetIndex: null,
			entityList: [],
			resultModel: null,
			entityCode: null,
			sourceData: null,
			sqlString: '',
			executing: false,
			sqlName: '',
			fetchingEntity: false,
			sourceId: null,
			executeData: {},
			//导出读取状态
			exportLoading: false,
			//实体读取状态
			entityLoading: false,
			presetModel: null,
			//预置脚本模型读取状态
			presetModelLoading: false,
			presetModal: false,
			entityModal: false,
			ds_code: '-_self_-',
			tabOn: 'entity',
			sampleLoad: false,
			structModel: {
				fields: [],
			},
			sampleModel: [],
			structData: [],
		};
	},
	computed: {
		editor() {
			return this.$refs.editor.editor;
		},
	},
	methods: {
		presetOutClick() {
			this.presetVisible = false;
		},
		presetConfigShow() {
			if (this.presetModel) {
				this.presetModal = true;
			} else {
				this.presetModelLoading = true;
				$.link(this.path.model)
					.then(res => {
						var model = billParser(res.data);
						//通过数据触发aciton 来添加数据转移sql语句的功能
						model.actions.push({
							code: 'setSql',
							locate: 'inline',
							type: 'event_trigger',
							icon: 'forward',
							param: {
								button_style: 'circle',
								button_type: 'success',
							},
						});
						if (model.fields) {
							for (let field of model.fields) {
								if (field.code === 'sql_content') {
									field.rangeset = {};
									field.rangeset.lang = 'sql';
								}
							}
						}
						this.$set(this, 'presetModel', model);
						this.presetModal = true;
					})
					.finally(() => {
						this.presetModelLoading = false;
					});
			}
		},
		execute() {
			var sqlString = this.sqlString;
			var selectString = this.editor.getSelection();
			if (selectString && selectString.length && $.trim(selectString).length) {
				sqlString = selectString;
			}
			this.executing = true;
			var postData = {
				//对执行语句进行base64编码
				sql: Base64.encode(sqlString),
			};
			if (this.sourceData) {
				postData.ds_code = this.sourceData.code;
			}
			$.link(this.path.execute, postData)
				.then(res => {
					this.$set(this, 'executeData', postData);
					this.sourceId = this.sourceData && this.sourceData.id;
					var model = {
						path: this.path.execute,
						actions: [],
						fields: res.data.model || [],
					};

					if ($.isArray(model)) model = model[0];
					let data = res.data.data || res.data;
					data = data.data || data;
					if ((!model.fields || !model.fields.length) && data && data.length) {
						model.fields = [];
						for (let i in data[0]) {
							model.fields.push({
								code: i,
								name: i,
							});
						}
					}
					this.$emit('updateStatus', {
						data: res.data.data,
						model,
						execute: postData,
						sql: this.sqlString,
					});
					this.$set(this, 'resultData', res.data.data);
					this.$set(this, 'resultModel', model);
				})
				.finally(() => {
					this.executing = false;
				});
		},
		tableUpdateStatus({ data }) {
			this.$emit('updateStatus', { data: data });
		},
		exportConfirm() {
			return new Promise((resolve, reject) => {
				this.$Modal.confirm({
					title: '确认操作',
					content: this.confirmText(),
					onOk: () =>
						this.exportData()
							.then(res => {
								resolve(res);
							})
							.catch(res => {
								reject(res);
							}),
					onCancel() {
						resolve();
					},
				});
			});
		},
		fetchPreset() {
			this.presetIndex = null;
			$.link(this.path.preset.list, {}).then(res => {
				var data = res.data.data || res.data;
				this.$set(this, 'presetList', data);
			});
		},
		savePreset() {
			var data = {};
			if (this.presetIndex) {
				data = {
					...this.presetList[this.presetIndex],
				};
			}
			data.code = this.sqlString;
			data.name = this.sqlName;
			$.link(this.path.preset.save, data).then(res => {
				this.fetchPreset();
				this.$Notice.success({
					title: '数据保存成功',
				});
			});
		},
		deletePreset(id) {
			$.link(this.path.preset.delete, [id]).then(res => {
				this.$Notice.success({
					title: '数据删除成功',
				});
				this.fetchPreset();
			});
		},
		exportData() {
			var data = {};
			var rows = this.$refs.dataTable.getSelectedIds();
			data.param = this.executeData;
			if (rows && rows.length) {
				data.rows = rows;
			}
			this.exportLoading = true;
			return $.download(this.path.export, data)
				.then(res => {
					this.$Notice.success({
						title: '输出导出成功',
					});
				})
				.finally(() => {
					this.exportLoading = false;
				});
		},
		confirmText() {
			var count = this.$refs.dataTable.totalCount;
			var text = '';
			var rows = this.$refs.dataTable.getSelectedIds();
			if (rows && rows.length) {
				count = rows.length;
				text = '确认导出当前选中的' + count + '条数据';
			} else {
				if (count) {
					text = '确认导出当前过滤的' + count + '条数据';
				} else {
					text = '确认导出当前过滤的数据';
				}
			}
			return text;
		},
		clearSql() {
			this.sqlString = '';
		},
		//与之数据列表action触发
		presetActionEvent(e) {
			if (e.code === 'setSql') {
				this.presetModal = false;
				this.sqlString = e.data.sql_content;
			}
		},
		sourceChange(data) {
			this.ds_code = data.code;
			this.sourceData = data;
			this.fetchEntity(this.sourceData && this.sourceData.code);
		},
		//查询实体
		fetchEntity(code) {
			this.$set(this, 'entityList', []);
			code = this.ds_code;
			this.entityLoading = true;
			$.link(this.path.entity, null, {
				param: {
					code,
				},
			})
				.then(res => {
					this.entityCode = null;
					this.$set(this, 'entityList', res.data);
					this.$emit('updateStatus', { source: this.sourceData, entity: res.data });
				})
				.finally(() => {
					this.entityLoading = false;
				});
		},
		//选择实体变化 暂时无用
		entityChange(index) {
			this.entityCode = this.entityList[index] && this.entityList[index].TABLE_NAME;
		},
		//选中加载·一个预置选项
		selectpresetList(index) {
			this.presetIndex = index;
			this.sqlName = this.presetList[this.presetIndex].name;
			this.sqlString = this.presetList[this.presetIndex].code;
			this.presetVisible = false;
		},
		viewEntity(name) {
			this.entityModal = true;
			$.link(
				this.path.struct,
				{},
				{
					param: {
						ds_code: this.ds_code,
						entity_code: name,
					},
				}
			).then(res => {
				this.tabOn = 'entity';
				this.sampleLoad = false;
				if (res.data && res.data[0]) {
					this.structModel.fields = [];
					this.sampleModel.fields = [];
					for (let i in res.data) {
						let field = res.data[i];
						this.sampleModel.fields.push(field);
					}
					for (let i in res.data[0]) {
						this.structModel.fields.push({
							code: i,
							name: i,
							type: 'code',
						});
					}
				}
				this.sampleModel.path = $.composePath(this.path.sample, {
					ds_code: this.ds_code,
					entity_code: name,
				});
				this.$set(this, 'structData', res.data);
			});
		},
		copyName(name) {
			this.sqlString = `${this.sqlString} ${name}`;
		},
		tabClick: function(index) {
			if (index === 'sample') {
				this.sampleLoad = true;
				this.$refs.sampleTable && this.$refs.sampleTable.update();
			}
		},
	},
	created() {
		if (this.statusData) {
			this.executeData = this.statusData.execute;
			this.resultData = this.statusData.data;
			this.resultModel = this.statusData.model;
			this.entityList = this.statusData.entity;
			this.sqlString = this.statusData.sql;
		} else {
			this.fetchEntity();
		}
	},
	directives: {
		HeightLight,
		ClickOut,
	},
	components: {
		Selector,
		SelectPanel,
		CodeEditor,
		DataTable,
		GridPanel,
		Modals,
	},
};
</script>
<style lang="less">
.node-db-console {
	height: 100%;
	flex: 1 1 0;
	display: flex;
	flex-direction: column;
	.selecor-label {
		width: 70px;
	}
	.preset-select {
		border-left: 6px solid #2d8cf0;
	}
	.name-input {
		margin-bottom: 12px;
		.ivu-input-group-prepend {
			padding: 0 16px;
		}
	}
	.item-name {
		padding-right: 12px;
		.pull-right {
			margin-right: -16px;
		}
	}

	.ivu-row-flex {
		height: 100%;
		flex: 1;
	}
	.ivu-btn {
		margin-right: 4px;
		&.pull-right {
			margin-left: 4px;
			margin-right: 0;
		}
	}
	.left-box {
		padding-right: 8px;
		display: flex;
		flex-direction: column;
		.select-list {
			flex: 1;
			display: flex;
			flex-direction: column;
			.select-list-body {
				flex: 1;
				display: flex;
				flex-direction: column;
				.list-wrapper {
					flex: 1;
					height: 100%;
				}
			}
		}
	}
	.right-box {
		padding-left: 8px;
		border-left: 1px solid #ddd;
		display: flex;
		flex-direction: column;
		overflow: hidden;
	}
	.CodeMirror {
		height: 106px;
	}
	hr {
		margin: 8px 0;
	}
	.data-box {
		flex: 1 1 0;
		overflow: hidden;
	}
	.item-code {
		padding: 8px;
	}
	.entity-option {
		word-break: break-word;
		.type-code {
			color: #c1c1c1;
			float: right;
			.ivu-icon {
				font-size: 16px;
			}
		}
	}
}
</style>
